package service

import (
	"bytes"
	"compress/zlib"
	"encoding/base64"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/spf13/viper"
)

// PlantUMLService 处理PlantUML图表渲染
type PlantUMLService struct {
	serverURL   string
	timeout     time.Duration
	client      *http.Client
	offlineMode bool
}

// NewPlantUMLService 创建新的PlantUML服务实例
func NewPlantUMLService() *PlantUMLService {
	serverURL := viper.GetString("plantuml.server_url")
	if serverURL == "" {
		serverURL = "http://localhost:8081"
	}

	timeout := viper.GetDuration("plantuml.timeout")
	if timeout == 0 {
		timeout = 10 * time.Second
	}

	offlineMode := viper.GetBool("plantuml.offline_mode")

	return &PlantUMLService{
		serverURL:   serverURL,
		timeout:     timeout,
		offlineMode: offlineMode,
		client: &http.Client{
			Timeout: timeout,
		},
	}
}

// RenderDiagram 渲染PlantUML图表
func (s *PlantUMLService) RenderDiagram(content string, format string) ([]byte, error) {
	// 检查离线模式
	if s.offlineMode {
		return nil, fmt.Errorf("PlantUML rendering is disabled in offline mode")
	}

	// 编码PlantUML内容
	encoded, err := s.encodePlantUML(content)
	if err != nil {
		return nil, fmt.Errorf("failed to encode PlantUML content: %w", err)
	}

	// 构建请求URL
	requestURL := fmt.Sprintf("%s/%s/%s", s.serverURL, format, encoded)

	// 发送HTTP请求
	resp, err := s.client.Get(requestURL)
	if err != nil {
		return nil, fmt.Errorf("failed to request PlantUML server: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("PlantUML server returned status: %d", resp.StatusCode)
	}

	// 读取响应内容
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)
	}

	return data, nil
}

// GetDiagramURL 获取PlantUML图表URL
func (s *PlantUMLService) GetDiagramURL(content string, format string) (string, error) {
	// 编码PlantUML内容
	encoded, err := s.encodePlantUML(content)
	if err != nil {
		return "", fmt.Errorf("failed to encode PlantUML content: %w", err)
	}

	// 构建URL
	diagramURL := fmt.Sprintf("%s/%s/%s", s.serverURL, format, encoded)
	return diagramURL, nil
}

// encodePlantUML 编码PlantUML内容
func (s *PlantUMLService) encodePlantUML(content string) (string, error) {
	// 确保内容以@startuml开始和@enduml结束
	content = strings.TrimSpace(content)
	if !strings.HasPrefix(content, "@startuml") {
		content = "@startuml\n" + content
	}
	if !strings.HasSuffix(content, "@enduml") {
		content = content + "\n@enduml"
	}

	// 压缩内容
	var buf bytes.Buffer
	writer := zlib.NewWriter(&buf)
	_, err := writer.Write([]byte(content))
	if err != nil {
		return "", err
	}
	writer.Close()

	// Base64编码
	compressed := buf.Bytes()
	encoded := base64.StdEncoding.EncodeToString(compressed)

	// PlantUML特殊的URL安全编码
	encoded = strings.ReplaceAll(encoded, "+", "-")
	encoded = strings.ReplaceAll(encoded, "/", "_")
	encoded = strings.ReplaceAll(encoded, "=", "")

	return encoded, nil
}

// ValidateDiagram 验证PlantUML图表语法
func (s *PlantUMLService) ValidateDiagram(content string) error {
	// 基本语法检查
	content = strings.TrimSpace(content)
	
	// 检查是否包含基本的PlantUML结构
	if !strings.Contains(content, "@startuml") && !strings.Contains(content, "@enduml") {
		// 如果没有开始和结束标记，尝试添加它们进行验证
		testContent := "@startuml\n" + content + "\n@enduml"
		return s.validateContent(testContent)
	}
	
	return s.validateContent(content)
}

// validateContent 验证内容
func (s *PlantUMLService) validateContent(content string) error {
	// 检查是否有匹配的开始和结束标记
	startCount := strings.Count(content, "@startuml")
	endCount := strings.Count(content, "@enduml")
	
	if startCount != endCount {
		return fmt.Errorf("mismatched @startuml and @enduml tags")
	}
	
	if startCount == 0 {
		return fmt.Errorf("missing @startuml tag")
	}
	
	// 检查是否包含有效的PlantUML语法元素
	validElements := []string{
		"participant", "actor", "boundary", "control", "entity", "database",
		"class", "interface", "abstract", "enum",
		"package", "namespace", "folder",
		"node", "cloud", "component", "frame",
		"->", "<-", "--", "..", ":",
	}
	
	hasValidElement := false
	lowerContent := strings.ToLower(content)
	for _, element := range validElements {
		if strings.Contains(lowerContent, element) {
			hasValidElement = true
			break
		}
	}
	
	if !hasValidElement {
		return fmt.Errorf("no valid PlantUML elements found")
	}
	
	return nil
}

// GetSupportedFormats 获取支持的输出格式
func (s *PlantUMLService) GetSupportedFormats() []string {
	return []string{
		"png",  // PNG图片
		"svg",  // SVG矢量图
		"eps",  // EPS格式
		"pdf",  // PDF格式
		"txt",  // 文本格式
		"utxt", // Unicode文本
	}
}

// IsFormatSupported 检查格式是否支持
func (s *PlantUMLService) IsFormatSupported(format string) bool {
	supportedFormats := s.GetSupportedFormats()
	for _, supported := range supportedFormats {
		if supported == format {
			return true
		}
	}
	return false
}

// GetServerInfo 获取PlantUML服务器信息
func (s *PlantUMLService) GetServerInfo() (map[string]interface{}, error) {
	infoURL := s.serverURL + "/version"
	
	resp, err := s.client.Get(infoURL)
	if err != nil {
		return nil, fmt.Errorf("failed to get server info: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("server returned status: %d", resp.StatusCode)
	}
	
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)
	}
	
	return map[string]interface{}{
		"server_url": s.serverURL,
		"timeout":    s.timeout.String(),
		"version":    string(data),
		"formats":    s.GetSupportedFormats(),
	}, nil
}